package com.sap.sap_mangers.service.Impl;


import com.alibaba.fastjson.JSON;
import com.sap.sap_mangers.Vo.JoinVo.ClickJoinButtonVo;
import com.sap.sap_mangers.Vo.JoinVo.JoinManagerVo;
import com.sap.sap_mangers.Vo.SapVo.SapPeopleSolutionVo;
import com.sap.sap_mangers.Vo.SapVo.SessionNumber;
import com.sap.sap_mangers.Vo.UserVo.OnlinePeople.OnlineFullVo;
import com.sap.sap_mangers.Vo.UserVo.OnlinePeople.OnlineTime;
import com.sap.sap_mangers.Vo.UserVo.SapUserSessionList;
import com.sap.sap_mangers.Vo.UserVo.UserAndName;
import com.sap.sap_mangers.Vo.UserVo.UserMessage;
import com.sap.sap_mangers.domain.LoginUser;
import com.sap.sap_mangers.dto.user.NoticeDto;
import com.sap.sap_mangers.dto.user.RegisterUser;
import com.sap.sap_mangers.dto.user.SoftAssociationChange;
import com.sap.sap_mangers.email.IMailService;
import com.sap.sap_mangers.mapper.BmsMapper;
import com.sap.sap_mangers.mapper.JoinMapper;
import com.sap.sap_mangers.mapper.MenuMapper;
import com.sap.sap_mangers.mapper.UserMapper;
import com.sap.sap_mangers.pojo.*;
import com.sap.sap_mangers.service.BillService;
import com.sap.sap_mangers.service.CacheService;
import com.sap.sap_mangers.service.DynamicService;
import com.sap.sap_mangers.service.UserService;
import com.sap.sap_mangers.until.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * @author 阿东
 * @date 2022/6/30 [23:55]
 */
@Service
public class UserServiceImpl implements UserService {

    private final Logger log = LoggerFactory.getLogger(this.getClass());
    @Resource
    DataSourceTransactionManager transactionManager;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private CosUntil cosUntil;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private IMailService iMailService;
    @Autowired
    private BmsMapper bmsMapper;
    @Autowired
    private JoinMapper joinMapper;
    @Autowired
    private BillService billService;
    @Autowired
    private DynamicService dynamicService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private MenuMapper menuMapper;

    @Override
    public User getUserByUserName(String username) {
        return userMapper.getUserByUserName(username);
    }

    @Override
    public List<SapUserSessionList> getUserSessionList(Integer session) {
        return userMapper.getUserSessionList(session);
    }

    @Override
    public UserMessage getUserMessage(String username) {
        UserMessage userMessage;
        if (username == null) {
            userMessage = userMapper.getUserMessage(JwtUtil.getUserForToken());
            String historyPosts = userMapper.getHistoryPosts(JwtUtil.getUserForToken());
            userMessage.setPosts(historyPosts);
        } else {
            userMessage = userMapper.getUserMessage(username);
            String historyPosts = userMapper.getHistoryPosts(username);
            userMessage.setPosts(historyPosts);
        }
        return userMessage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SimpleJson registerUser(RegisterUser registerUser) {
        if (registerUser.getUsername().length() != ConstantUntil.USERNAME_LENGTH) {
            return new SimpleJson(1, "账户长度必须为8，建议使用学号作为账号");
        }
        String username = userMapper.getUsername(registerUser.getUsername());
        if (username != null) {
            return new SimpleJson(1, "账户已经存在，如果忘记密码请修改密码");
        }
        String qq = userMapper.getQQ(registerUser.getQq());
        if (qq != null) {
            return new SimpleJson(3, "该qq已被其他用户绑定,请输入其他qq");
        }
        String newPasswordForEncoder = passwordEncoder.encode(registerUser.getPassword());
        registerUser.setPassword(newPasswordForEncoder);

        userMapper.registerUser(registerUser);
        Integer session = Integer.valueOf(userMapper.getJoinSapTime());
        try {
            userMapper.registerUserDetails(registerUser.getUsername(), registerUser.getName(), session, new Timestamp(System.currentTimeMillis()));
            userMapper.addRole(registerUser.getUsername(), ConstantUntil.USER_ROLE_PERMISSIONS_FIVE);
        } catch (Exception e) {
            e.printStackTrace();
            return new SimpleJson(2, "数据库存在详细信息，但是账号不存在，异常情况请联系会长");
        }
        userMapper.addHistory(registerUser.getUsername(), registerUser.getName(), new Timestamp(System.currentTimeMillis()), "游客");
        userMapper.addMessageBoardRecord(Integer.parseInt(registerUser.getUsername()));
        return new SimpleJson(0, "注册成功！！！");
    }

    @Override
    public SimpleJson updateUserDefinition(DetailsUser detailsUser) {
        System.out.println(detailsUser);
        try {
            userMapper.updateUserDefinition(detailsUser);
            UserMessage userMessage = getUserMessage(null);
            cacheService.updateUser(String.valueOf(detailsUser.getUserDetailsId()));
            return SimpleJson.buildData(userMessage);
        } catch (Exception e) {
            e.printStackTrace();
            return new SimpleJson("错误操作");
        }
    }


    @Override
    public SimpleJson identityUsernameAndQq(User user) {
        if (Objects.equals(user.getCode(), cacheService.getPasswordCode(user.getUsername()))) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            userMapper.updatePasswordByUsername(user);
            cacheService.updateUser(user.getUsername());
            return SimpleJson.SUCCESS;
        }
        return SimpleJson.FAILURE;
    }

    @Override
    public SimpleJson generateCode(User user) {
        try {
            User userByUserName = userMapper.getUserByUserName(user.getUsername());
            if (userByUserName.getQq() == null || userByUserName.getQq().length() == 0 || "无".equals(userByUserName.getQq())) {
                return new SimpleJson(1, "密码修改出错，不存在QQ号记录，请先绑定QQ号");
            }
            String randomNum = RandomUntil.getRandomNum(ConstantUntil.PASSWORD_CODE_LENGTH);
            cacheService.setPasswordCode(randomNum, user.getUsername());
            String emailText = EmailUntil.sendEmailForUpdatePasswordCheck(randomNum);
            try {
                iMailService.sendHtmlMail(userByUserName.getQq() + "@qq.com", "修改密码验证码", emailText);
            } catch (Exception e) {
                e.printStackTrace();
                return SimpleJson.FAILURE;
            }
            return SimpleJson.SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SimpleJson.FAILURE;

    }

    @Override
    public SimpleJson addQq(String qq, String username) {
        try {
            userMapper.updateQQ(qq, username);
        } catch (Exception e) {
            return SimpleJson.FAILURE;
        }
        return SimpleJson.SUCCESS;
    }

    @Override
    public SimpleJson getUserHeadShot(String username) {
        return new SimpleJson(0, "获取成功", cacheService.getHeaderCache(cacheService.getHeaderCacheMap(), username));
    }

    @Override
    public SimpleJson updateHeadShot(MultipartFile multipartFile) {
        String usernameUrl = JwtUtil.getUserForToken() + "headerShot.jpg";
        String cosUrl = "SapUserHeadShot/" + usernameUrl;
        String url;
        try {
            url = cosUntil.getCosUrl(multipartFile, cosUrl);
        } catch (IOException e) {
            return new SimpleJson(5, "图片上传失败！");
        }
        userMapper.updateHeadShot(JwtUtil.getUserForToken(), url);
        String headerUrl = cacheService.updateUserHeaderUrl(cacheService.getHeaderCacheMap(), JwtUtil.getUserForToken());
        return new SimpleJson(0, "头像更新成功", headerUrl);
    }

    @Override
    public SimpleJson getNoticeByUsername() {
        List<SapUserNotice> noticeByUsername = userMapper.getNoticeByUsername(JwtUtil.getUserForToken());
        for (SapUserNotice sapUserNotice : noticeByUsername) {
            sapUserNotice.setUserName(cacheService.getRealNameCache(cacheService.getRealNameCacheMap(), sapUserNotice.getUserNoticeUsername()));
            sapUserNotice.setManagerName(cacheService.getRealNameCache(cacheService.getRealNameCacheMap(), sapUserNotice.getUserNoticeManager()));
            sapUserNotice.setImageUrl(cacheService.getHeaderCache(cacheService.getHeaderCacheMap(), sapUserNotice.getUserNoticeManager()));
        }
        return new SimpleJson(0, "获取成功", noticeByUsername);
    }

    @Override
    public SimpleJson getNoticeMessage() {
        long start1 = System.currentTimeMillis();
        long start2 = System.currentTimeMillis();
        List<SapUserNotice> noticeMessage = userMapper.getNoticeMessage();
        long end2 = System.currentTimeMillis();
        log.warn("系统执行时间1:{}", end2 - start2);
        long start3 = System.currentTimeMillis();
        Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
        for (SapUserNotice sapUserNotice : noticeMessage) {
            sapUserNotice.setUserName(cacheService.getRealNameCache(realNameCacheMap, sapUserNotice.getUserNoticeUsername()));
            sapUserNotice.setManagerName(cacheService.getRealNameCache(realNameCacheMap, sapUserNotice.getUserNoticeManager()));
            sapUserNotice.setImageUrl(cacheService.getRealNameCache(realNameCacheMap, sapUserNotice.getUserNoticeManager()));
        }
        long end3 = System.currentTimeMillis();
        log.warn("系统执行时间2:{}", end3 - start3);
        long end1 = System.currentTimeMillis();
        log.warn("系统执行时间3:{}", end1 - start1);
        return new SimpleJson(1, "获取成功", noticeMessage);
    }

    @Override
    public SimpleJson confirmationMessage(String noticeId) {
        try {
            userMapper.updateNotice(JwtUtil.getUserForToken(), Integer.valueOf(noticeId), new Timestamp(System.currentTimeMillis()));
        } catch (Exception e) {
            e.printStackTrace();
            return new SimpleJson(1, "确认消息失败!");
        }
        return SimpleJson.SUCCESS;
    }

    @Override
    public SimpleJson sendNotice(NoticeDto noticeDto) {
        try {
            SapUserNotice sapUserNotice = new SapUserNotice();
            sapUserNotice.setUserNoticeUsername(noticeDto.getUsername());
            sapUserNotice.setUserNoticeContext(noticeDto.getContext());
            sapUserNotice.setUserNoticeManager(JwtUtil.getUserForToken());
            SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0, 0);
            sapUserNotice.setUserNoticeRank(snowflakeIdWorker.nextId());
            sapUserNotice.setUserNoticeCreateTime(new Timestamp(System.currentTimeMillis()));
            userMapper.addNotice(sapUserNotice);
        } catch (Exception e) {
            e.printStackTrace();
            return new SimpleJson(1, "消息发送失败");
        }
        return new SimpleJson(0, "消息发送成功");
    }

    @Override
    public User getPresidentUserInfo() {
        return userMapper.getPresidentUser();
    }

    @Override
    public void sendNoticeAuto(NoticeDto noticeDto) {
        SapUserNotice sapUserNotice = new SapUserNotice();
        sapUserNotice.setUserNoticeUsername(noticeDto.getUsername());
        sapUserNotice.setUserNoticeContext(noticeDto.getContext());
        sapUserNotice.setUserNoticeManager("66666666");
        SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0, 0);
        sapUserNotice.setUserNoticeRank(snowflakeIdWorker.nextId());
        sapUserNotice.setUserNoticeCreateTime(new Timestamp(System.currentTimeMillis()));
        userMapper.addNotice(sapUserNotice);
    }

    /**
     * 换届，就要对所有信息进行更改！！！
     *
     * @param softAssociationChange 换届信息
     * @return 视图
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SimpleJson softAssociationChange(SoftAssociationChange softAssociationChange) {
        List<Minister> minister = userMapper.getMinister();
        for (Minister user : minister) {
            String posts = userMapper.getUserPostByUsername(user.getUsername());
            try {
                userMapper.updateHistory(user.getUsername(), dynamicService.getYear() + "届" + posts);
            } catch (Exception e) {
                e.printStackTrace();
                userMapper.addHistory(user.getUsername(), cacheService.getRealNameCache(cacheService.getRealNameCacheMap(), user.getUsername()), new Timestamp(System.currentTimeMillis()), dynamicService.getYear() + "届" + posts);
            }
            userMapper.updateRole(10, user.getUsername());
            userMapper.updateUserRole(user.getUsername(), ConstantUntil.USER_ROLE_PERMISSIONS_THREE);
        }
        dynamicService.changeYear();
        String president = softAssociationChange.getPresident();
        userMapper.updateRole(1, president);
        userMapper.addPosts(president, userMapper.getPostByRole(1), Integer.valueOf(dynamicService.getYear()), 1);
        userMapper.updateHistory(president, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(president));
        userMapper.updateUserRole(president, ConstantUntil.USER_ROLE_PERMISSIONS_ONE);
        String secretary = softAssociationChange.getSecretary();
        userMapper.updateRole(2, secretary);
        userMapper.addPosts(secretary, userMapper.getPostByRole(2), Integer.valueOf(dynamicService.getYear()), 2);
        userMapper.updateHistory(secretary, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(secretary));
        userMapper.updateUserRole(secretary, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        List<String> vicePresident = softAssociationChange.getVicePresident();
        for (String username : vicePresident) {
            userMapper.updateRole(3, username);
            userMapper.addPosts(username, userMapper.getPostByRole(3), Integer.valueOf(dynamicService.getYear()), 3);
            userMapper.updateHistory(username, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(username));
            userMapper.updateUserRole(username, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        }
        String ministerOfAcademicAffairs = softAssociationChange.getMinisterOfAcademicAffairs();
        userMapper.updateRole(4, ministerOfAcademicAffairs);
        userMapper.addPosts(ministerOfAcademicAffairs, userMapper.getPostByRole(4), Integer.valueOf(dynamicService.getYear()), 4);
        userMapper.updateHistory(ministerOfAcademicAffairs, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(ministerOfAcademicAffairs));
        userMapper.updateUserRole(ministerOfAcademicAffairs, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        List<String> deputyMinisterOfAcademicAffairs = softAssociationChange.getDeputyMinisterOfAcademicAffairs();
        for (String deputyMinisterOfAcademicAffair : deputyMinisterOfAcademicAffairs) {
            userMapper.updateRole(5, deputyMinisterOfAcademicAffair);
            userMapper.addPosts(deputyMinisterOfAcademicAffair, userMapper.getPostByRole(5), Integer.valueOf(dynamicService.getYear()), 5);
            userMapper.updateHistory(deputyMinisterOfAcademicAffair, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(deputyMinisterOfAcademicAffair));
            userMapper.updateUserRole(deputyMinisterOfAcademicAffair, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        }
        String ministerOfSynthesis = softAssociationChange.getMinisterOfSynthesis();
        userMapper.updateRole(6, ministerOfSynthesis);
        userMapper.addPosts(ministerOfSynthesis, userMapper.getPostByRole(6), Integer.valueOf(dynamicService.getYear()), 6);
        userMapper.updateHistory(ministerOfSynthesis, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(ministerOfSynthesis));
        userMapper.updateUserRole(ministerOfSynthesis, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        List<String> deputyMinisterOfSynthesis = softAssociationChange.getDeputyMinisterOfSynthesis();
        for (String ofSynthesis : deputyMinisterOfSynthesis) {
            userMapper.updateRole(7, ofSynthesis);
            userMapper.addPosts(ofSynthesis, userMapper.getPostByRole(7), Integer.valueOf(dynamicService.getYear()), 7);
            userMapper.updateHistory(ofSynthesis, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(ofSynthesis));
            userMapper.updateUserRole(ofSynthesis, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        }
        String ministerOfPropaganda = softAssociationChange.getMinisterOfPropaganda();
        userMapper.updateRole(8, ministerOfPropaganda);
        userMapper.addPosts(ministerOfPropaganda, userMapper.getPostByRole(8), Integer.valueOf(dynamicService.getYear()), 8);
        userMapper.updateHistory(ministerOfPropaganda, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(ministerOfPropaganda));
        userMapper.updateUserRole(ministerOfPropaganda, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        List<String> deputyMinisterOfPublicity = softAssociationChange.getDeputyMinisterOfPublicity();
        for (String username : deputyMinisterOfPublicity) {
            userMapper.updateRole(9, username);
            userMapper.addPosts(username, userMapper.getPostByRole(9), Integer.valueOf(dynamicService.getYear()), 9);
            userMapper.updateHistory(username, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(username));
            userMapper.updateUserRole(username, ConstantUntil.USER_ROLE_PERMISSIONS_TWO);
        }

        //换届会导致升级会员的管理表全部重置
        fillJoinManagerTable();
        //换届时重置图书管理表
        fillBmsManagerTable();

        return SimpleJson.SUCCESS;
    }


    @Override
    public SimpleJson updateRolePosts(String username, Integer role, Integer rank) {
        try {
            userMapper.updateUserRole(username, role);
            userMapper.updateHistory(username, dynamicService.getYear() + "届" + userMapper.getUserPostByUsername(username));
            userMapper.updateRole(rank, username);
        } catch (Exception e) {
            e.printStackTrace();
            return new SimpleJson(1, "sql执行错误");
        }
        return null;
    }

    @Override
    public List<Minister> getMinister() {
        return userMapper.getMinister();
    }

    @Override
    public List<Minister> getOrdinaryMembers() {
        return userMapper.getOrdinaryMembers();
    }

    @Override
    public List<SapIp> getIp() {
        return userMapper.getIp();
    }

    @Override
    public void addIp(SapIp ip) {
        userMapper.addIp(ip);
    }

    @Override
    public SimpleJson getSapPeopleNumberInfo() {
        SapPeopleSolutionVo sapPeopleSolutionVo = new SapPeopleSolutionVo();
        sapPeopleSolutionVo.setSexNumberInfoList(userMapper.getSexNumberInfo());
        List<SessionNumber> sessionNumbers = userMapper.getSessionNumber();
        ArrayList<Integer> year = new ArrayList<>();
        ArrayList<Integer> number = new ArrayList<>();
        //因为数据库2021年才有，所以2018-2020年的数据数据库并不存在;
        year.add(2018);
        number.add(12);
        year.add(2019);
        number.add(27);
        year.add(2020);
        number.add(54);
        for (SessionNumber sessionNumber : sessionNumbers) {
            if (sessionNumber.getSession() == 2020) {
                continue;
            }
            year.add(sessionNumber.getSession());
            number.add(sessionNumber.getNumber());
        }
        sapPeopleSolutionVo.setYear(year);
        sapPeopleSolutionVo.setNumber(number);
        return new SimpleJson(0, "获取成功", sapPeopleSolutionVo);
    }

    @Override
    public List<SapIp> getIpByUsername(String username) {
        return userMapper.getIpByUsername(username);
    }

    @Override
    public String getPresidentUsername() {
        return userMapper.getPresidentUserName();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void fillJoinManagerTable() {
        //删除所有原负责人付款码的cos储存
        List<SapJoinManager> allSapJoinManagers = joinMapper.getAllSapJoinManagers();
        for (SapJoinManager manager : allSapJoinManagers) {
            if (manager.getWeChatCollectionCode() != null) {
                cosUntil.deleteCosUrl(manager.getWeChatCollectionCode());
            }
            if (manager.getAlipayCollectionCode() != null) {
                cosUntil.deleteCosUrl(manager.getAlipayCollectionCode());
            }
        }
        //清空数据库
        joinMapper.clearJoinManagerTable();
        //填充新数据
        List<String> allMinistersUsername = userMapper.getAllMinistersUsername();
        joinMapper.fillJoinManagerTable(allMinistersUsername);
        //关闭入会升级功能(申请入会相关接口)
        cacheService.closeSapIfOpenJoinFunction();
    }

    @Override
    public synchronized SimpleJson changeJoinManagerResponsible(String username) {
        String userForToken = JwtUtil.getUserForToken();
        String presidentUserName = userMapper.getPresidentUserName();
        if (!presidentUserName.equals(userForToken)) {
            //只允许会长使用
            return new SimpleJson(1, "权限不足");
        }
        SapJoinManager sapJoinManager = joinMapper.getSapJoinManager(username);
        if (sapJoinManager == null) {
            return new SimpleJson(2, "未在入会管理员中找到该学号");
        }
        //是否负责字段设为相反的值
        joinMapper.updateResponsible(username, !sapJoinManager.getResponsible());
        return SimpleJson.SUCCESS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SimpleJson setCollectionCode(MultipartFile collectionCode, Integer type) {
        //收款码种类是否合理
        if (type == null) {
            return new SimpleJson(5, "类型参数不合理");
        } else if (!type.equals(0) && !type.equals(1)) {
            return new SimpleJson(5, "类型参数不合理");
        }
        //验证是否为负责人(管理层)
        String userForToken = JwtUtil.getUserForToken();
        SapJoinManager sapJoinManager = joinMapper.getSapJoinManager(userForToken);
        if (sapJoinManager == null) {
            return new SimpleJson(1, "不是入会管理员，无法上传");
        }

        //验证图片
        if (collectionCode == null) {
            return new SimpleJson(2, "图片为空");
        }
        String originalFilename = collectionCode.getOriginalFilename();
        assert originalFilename != null;
        if (!originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")) {
            return new SimpleJson(3, "图片格式不正确，请为.png 或 .jpg，添加失败", null);
        }

        //图片上传cos，获取地址
        String imageName = UUID.randomUUID() + "_" + originalFilename;
        String cosUrl;
        try {
            cosUrl = cosUntil.getCosUrl(collectionCode, "SapImage/collectionCode/" + CommonUtils.getTimeDirectory() + "/" + imageName);
        } catch (IOException e) {
            return new SimpleJson(4, "图片上传异常，请重试并联系会长，异常信息：" + e.getMessage());
        }

        //删除cos中的原图片(如果存在)并将新的cos地址写进数据库
        if (type.equals(0)) {
            //微信
            String weChatCollectionCode = sapJoinManager.getWeChatCollectionCode();
            if (weChatCollectionCode != null) {
                //删除原收款码图片
                cosUntil.deleteCosUrl(weChatCollectionCode);
            }
            joinMapper.setWeChatCollectionCode(userForToken, cosUrl);
        } else if (type.equals(1)) {
            //支付宝
            String alipayCollectionCode = sapJoinManager.getAlipayCollectionCode();
            if (alipayCollectionCode != null) {
                cosUntil.deleteCosUrl(alipayCollectionCode);
            }
            joinMapper.setAlipayCollectionCode(userForToken, cosUrl);
        }
        return SimpleJson.SUCCESS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SimpleJson deleteCollectionCode(Integer type) {
        //检测参数是否合理
        if (type == null) {
            return new SimpleJson(1, "参数不合理");
        } else if (!type.equals(0) && !type.equals(1)) {
            return new SimpleJson(1, "参数不合理");
        }
        //检测是否为负责人
        String userForToken = JwtUtil.getUserForToken();
        SapJoinManager sapJoinManager = joinMapper.getSapJoinManager(userForToken);
        if (sapJoinManager == null) {
            return new SimpleJson(2, "不是协会管理层");
        }
        //删除cos上的收款码图片和将数据库收款码地址字段置空
        if (type.equals(0)) {
            //微信
            String weChatCollectionCode = sapJoinManager.getWeChatCollectionCode();
            if (weChatCollectionCode != null) {
                //cos删除图片
                cosUntil.deleteCosUrl(weChatCollectionCode);
                //数据库字段置空
                joinMapper.setWeChatCollectionCode(userForToken, null);
            }
        } else if (type.equals(1)) {
            //支付宝
            String alipayCollectionCode = sapJoinManager.getAlipayCollectionCode();
            if (alipayCollectionCode != null) {
                cosUntil.deleteCosUrl(alipayCollectionCode);
                joinMapper.setAlipayCollectionCode(userForToken, null);
            }
        }
        return SimpleJson.SUCCESS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SimpleJson clickJoinButton() {
        String userForToken = JwtUtil.getUserForToken();
        //检测是否已经是会员 (有token检测，能执行一定是能找到的账号)
        User user = userMapper.getUserByUserName(userForToken);
        if (user.getRole() != 12) {
            return new SimpleJson(2, "您已是会员");
        }
        //检测入会申请表记录
        SapJoinApplication application = joinMapper.getSapJoinApplication(userForToken);
        //没有查找到申请记录
        if (application == null) {
            //匹配负责人
            SapJoinManager sapJoinManager = choiceManager();
            if (sapJoinManager == null) {
                return new SimpleJson(3, "当前没有合适的负责人，请联系部长/会长处理");
            }
            //生成邀请码(6位随机大写字母)
            String invitationCode = StringCodeUtil.createUppercaseStringCode(6);

            //在入会申请表中插入新数据项
            //注意！！这个方法返回的内容不包含name!! 对象里面name字段为null ！！！！
            User managerUser = userMapper.getUserByUserName(sapJoinManager.getUsername());
            //从缓存获取真实姓名
            Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
            String applicantName = cacheService.getRealNameCache(realNameCacheMap, userForToken);
            String managerName = cacheService.getRealNameCache(realNameCacheMap, managerUser.getUsername());
            SapJoinApplication joinApplication = new SapJoinApplication(null, userForToken, applicantName, user.getQq(),
                    managerUser.getUsername(), managerName, managerUser.getQq(),
                    null, invitationCode, null, null, null);
            joinMapper.addSapJoinApplication(joinApplication);

            //同步管理员负责管理的人数 (分配的负责人+1)
            joinMapper.increaseManagementNumber(managerUser.getUsername());
            //返回管理员姓名/qq/收款码
            return new SimpleJson(0, "点击入会(升级)按钮", new ClickJoinButtonVo(managerName, managerUser.getQq(), sapJoinManager.getWeChatCollectionCode(), sapJoinManager.getAlipayCollectionCode(), null, null));
        }
        //已提交申请记录(填写过会费转账单号的记录) (填写过单号的记录不会过期)
        else if (application.getJoinApplicationPaymentTransferNumber() != null) {
            User managerUser = userMapper.getUserByUserName(application.getJoinManagerUsername());
            Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
            String managerName = cacheService.getRealNameCache(realNameCacheMap, managerUser.getUsername());
            //返回管理员QQ/姓名、邀请码、已填写的转账单号(用于自己核对，允许修改)
            return new SimpleJson(1, "获取成功", new ClickJoinButtonVo(managerName, managerUser.getQq(), null, null, application.getJoinApplicationInvitationCode(), application.getJoinApplicationPaymentTransferNumber()));
        }

        //申请记录已失效
        else if (application.getJoinLapse() == 1) {
            //重新匹配负责人，重置入会申请表 (不生成新数据项，不改变邀请码，其他都重置，所以直接查询原数据项进行修改) -> 返回新负责人的姓名/QQ/收款码
            return rematchManager(application);
        }

        //没有提交单号(没有执行入会申请接口)但记录未过期
        else if (application.getJoinLapse() != 1) {
            //之前匹配的负责人学号
            String oldManagerUsername = application.getJoinManagerUsername();
            //判断之前匹配的负责人当前是否仍有效(收款码/是否负责)
            SapJoinManager oldSapJoinManager = joinMapper.getSapJoinManager(oldManagerUsername);
            if (oldSapJoinManager.getResponsible()) {
                if (oldSapJoinManager.getWeChatCollectionCode() != null || oldSapJoinManager.getAlipayCollectionCode() != null) {
                    //单独更新create_time字段，避免填写单号时记录过期
                    joinMapper.updateCreateTime(userForToken);
                    //负责人仍有效(负责管理字段为true且至少有一种付款码) -> 返回管理员姓名/qq/收款码
                    User managerUser = userMapper.getUserByUserName(oldManagerUsername);
                    Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
                    String managerName = cacheService.getRealNameCache(realNameCacheMap, managerUser.getUsername());
                    return new SimpleJson(0, "点击入会(升级)按钮", new ClickJoinButtonVo(managerName, managerUser.getQq(), oldSapJoinManager.getWeChatCollectionCode(), oldSapJoinManager.getAlipayCollectionCode(), null, null));
                }
            }
            //重新匹配负责人，重置入会申请表 -> 返回新负责人的姓名/QQ/收款码
            return rematchManager(application);
        }

        //数据库数据有问题
        return new SimpleJson(4, "异常情况，联系部长/会长");
    }

    /**
     * 重新匹配负责人
     * 不生成新数据项，不改变邀请码，其他都重置，所以直接查询原数据项修改
     *
     * @param application 原入会申请记录
     * @return Json
     */
    private SimpleJson rematchManager(SapJoinApplication application) {
        //原负责人学号
        String oldManagerUsername = application.getJoinManagerUsername();
        //重新匹配负责人
        SapJoinManager sapJoinManager = choiceManager();
        if (sapJoinManager == null) {
            return new SimpleJson(3, "当前没有合适的负责人，请联系部长/会长处理");
        }
        //重新填写入会申请表 (不生成新数据项，不改变邀请码，其他都重置，所以直接查询原数据项进行修改)
        User managerUser = userMapper.getUserByUserName(sapJoinManager.getUsername());
        Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
        String managerName = cacheService.getRealNameCache(realNameCacheMap, managerUser.getUsername());
        //再查询一次原入会申请记录，用于修改成新记录
        //debug发现实际上再次查询返回的结果和application同一个引用,所以修改内容的同时application也被修改了，后面要使用到原application中的值只能在修改前单独定义变量保存
        SapJoinApplication joinApplication = joinMapper.getSapJoinApplication(application.getJoinApplicantUsername());
        joinApplication.setJoinManagerUsername(managerUser.getUsername());
        joinApplication.setJoinManagerName(managerName);
        joinApplication.setJoinManagerQq(managerUser.getQq());
        joinMapper.createSapJoinApplicationAgain(joinApplication);
        //管理员负责数量同步 (原负责人-1，新负责人+1)
        joinMapper.decreaseManagementNumber(oldManagerUsername);
        joinMapper.increaseManagementNumber(managerUser.getUsername());
        //返回新负责人的姓名/QQ/收款码
        return new SimpleJson(0, "点击入会(升级)按钮", new ClickJoinButtonVo(managerName, managerUser.getQq(), sapJoinManager.getWeChatCollectionCode(), sapJoinManager.getAlipayCollectionCode(), null, null));
    }

    /**
     * 工具方法 - 挑选一个合适的负责人
     * 方法同步
     *
     * @return 挑选的负责人
     */
    @Override
    public synchronized SapJoinManager choiceManager() {
        //获取负责管理且上传了至少一种收款码的管理员
        List<SapJoinManager> responsibleManagers = joinMapper.getAllResponsibleSapJoinManagers();
        if (responsibleManagers == null || responsibleManagers.isEmpty()) {
            return null;
        }
        //储存 需要负责处理的数量最少的管理员 的索引
        List<Integer> list = new ArrayList<>();
        list.add(0);
        int minNum = responsibleManagers.get(0).getNumber();
        for (int i = 1; i < responsibleManagers.size(); ++i) {
            int num = responsibleManagers.get(i).getNumber();
            if (num < minNum) {
                list.clear();
                list.add(i);
                minNum = num;
            } else if (num == minNum) {
                list.add(i);
            }
        }
        //选择其中一个
        return responsibleManagers.get(list.get(new Random().nextInt(list.size())));
    }

    @Override
    public SimpleJson submitApplication(String paymentTransferNumber) {
        //检测是否已是会员
        String userForToken = JwtUtil.getUserForToken();
        User user = userMapper.getUserByUserName(userForToken);
        if (user.getRole() != 12) {
            return new SimpleJson(1, "您已是会员");
        }
        //去除单号的前后空格
        paymentTransferNumber = paymentTransferNumber.trim();
        //检查填写的单号的长度
        if (paymentTransferNumber.length() < 10 || paymentTransferNumber.length() > 50) {
            return new SimpleJson(1, "单号格式无法判定，如已付款请联系管理员");
        }
        //获取申请记录
        SapJoinApplication sapJoinApplication = joinMapper.getSapJoinApplication(userForToken);
        if (sapJoinApplication == null) {
            //没有记录说明绕开了点击申请按钮过程
            return new SimpleJson(2, "流程异常，没有申请数据");
        }
        //填写/修改单号
        joinMapper.setJoinApplicationPaymentTransferNumber(sapJoinApplication.getJoinApplicationId(), paymentTransferNumber);

        //向负责人发送邮件、通知提醒、
        Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
        String userName = cacheService.getRealNameCache(realNameCacheMap, userForToken);
        User managerUser = userMapper.getUserByUserName(sapJoinApplication.getJoinManagerUsername());
        long nowTime = System.currentTimeMillis();
        String subject;
        String email = null;
        String notice;
        if (sapJoinApplication.getJoinApplicationPaymentTransferNumber() == null) {
            //原本单号为null -> 填写单号 (不再进行邮件通知，修改仍然发送)
            subject = "申请入会提醒";
            //email = EmailUntil.emailForUserApplyToJoin(userForToken, userName, user.getQq(), paymentTransferNumber, sapJoinApplication.getJoinApplicationInvitationCode());
            notice = "[申请入会]\n  学号为" + userForToken + "的同学:" +
                    userName + "\n在" + new Timestamp(nowTime) +
                    "填写了会费缴纳的转账单号" + paymentTransferNumber + "\n其对应邀请码为" + sapJoinApplication.getJoinApplicationInvitationCode()
                    + "\n其qq号为" + user.getQq() + "请核对后及时处理。";
        } else {
            //修改单号
            subject = "会费缴纳转账单号信息修改提醒";
            email = EmailUntil.emailForUseUpdateTransferNumber(userForToken, userName, user.getQq(), paymentTransferNumber, sapJoinApplication.getJoinApplicationInvitationCode());
            notice = "[会费单号修改]\n  学号为" + userForToken + "的同学:" +
                    userName + "\n在" + new Timestamp(nowTime) +
                    "修改了会费缴纳的转账单号" + paymentTransferNumber + "\n其对应邀请码为" + sapJoinApplication.getJoinApplicationInvitationCode()
                    + "\n其qq号为" + user.getQq() + "请核对后及时处理。";
        }

        sendNotice(new NoticeDto(managerUser.getUsername(), notice, null));
        //填写单号将不产生邮件，修改单号仍会发送
        if (email != null) {
            try {
                iMailService.sendHtmlMail(managerUser.getQq() + "@qq.com", subject, email);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //返回管理员姓名/QQ和邀请码、填写的转账单号
        String managerName = cacheService.getRealNameCache(realNameCacheMap, managerUser.getUsername());
        return new SimpleJson(0, "提交单号成功", new ClickJoinButtonVo(managerName, managerUser.getQq(), null, null, sapJoinApplication.getJoinApplicationInvitationCode(), sapJoinApplication.getJoinApplicationPaymentTransferNumber()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SimpleJson toExamine(String paymentTransferNumber, String invitationCode) throws Exception {
        if (paymentTransferNumber == null || invitationCode == null) {
            return new SimpleJson(7, "请输入参数");
        }
        //判断操作人是不是管理员
        String userForToken = JwtUtil.getUserForToken();
        SapJoinManager sapJoinManager = joinMapper.getSapJoinManager(userForToken);
        if (sapJoinManager == null) {
            return new SimpleJson(2, "权限不足");
        }
        //去除单号的前后空格
        paymentTransferNumber = paymentTransferNumber.trim();
        //根据邀请码查询申请表记录
        SapJoinApplication sapJoinApplication = joinMapper.getSapJoinApplicationByCode(invitationCode);
        if (sapJoinApplication == null) {
            return new SimpleJson(3, "邀请码不存在");
        }
        if (sapJoinApplication.getJoinApplicationPaymentTransferNumber() == null) {
            return new SimpleJson(4, "流程异常，未填写付款单号");
        }
        if (sapJoinApplication.getJoinApplicationResult() == 1) {
            return new SimpleJson(5, "该邀请码对应申请已被处理，请确认输入是否正确或是否已被处理");
        }
        //比对单号
        if (sapJoinApplication.getJoinApplicationPaymentTransferNumber().trim().equals(paymentTransferNumber)) {
            //单号相同 -> 升级会员
            String applicantUsername = sapJoinApplication.getJoinApplicantUsername();
            String applicantName = sapJoinApplication.getJoinApplicantName();
            userMapper.updateRole(11, applicantUsername);
            //修改申请表结果字段
            joinMapper.updateJoinApplicationResult(applicantUsername, 1);
            //对User_history的信息进行修改，从例如:游客-->2021级正式成员
            userMapper.updateHistory(applicantUsername, dynamicService.getYear() + "级正式成员");
            //对user_posts的信息进行添加，这个表存在每一届的所有正式成员以及部长及其会长
            userMapper.addPosts(applicantUsername, userMapper.getPostByRole(11), dynamicService.getYearForInt(), 11);
            //修改权限从游客到正式成员
            userMapper.updateUserRole(applicantUsername, ConstantUntil.USER_ROLE_PERMISSIONS_FOUR);
            //对接财务表
            //addBill有主动抛出异常
            billService.addBill(1, "会费缴纳", new BigDecimal(30), new Timestamp(System.currentTimeMillis()), "会费缴纳账单,执行审批接口的管理员学号为" + userForToken, null, applicantUsername, applicantName);
            //邮件/站内通知
            String email = EmailUntil.emailForUserJoinSuccess(applicantName);
            String notice = "[入会成功] 恭喜你成为软件协会的一员，期望你能在协会中有所收获，祝你成功！";
            sendNotice(new NoticeDto(applicantUsername, notice, null));
            //更新Redis里的权限内容(从数据库中获取添加)
            //从redis中获取用户信息
            Map<String, Object> cacheMap = redisCache.getCacheMap(ConstantUntil.SAP_LOGIN);
            String userJson = (String) cacheMap.get(applicantUsername);
            if(userJson!=null){
                LoginUser loginUser = JSON.parseObject(userJson, LoginUser.class);
                loginUser.setPermissions(menuMapper.selectPermsByUserId(applicantUsername));
                //把完整的用户信息存入redis username作为key
                String userJsonRedis = com.alibaba.fastjson2.JSON.toJSONString(loginUser);
                cacheService.loginCacheUserToRedis(applicantUsername, userJsonRedis);
            }
            try {
                iMailService.sendHtmlMail(sapJoinApplication.getJoinApplicantQq() + "@qq.com", "入会成功", email);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return SimpleJson.SUCCESS;
        } else {
            //不同 -> 提醒联系处理
            return new SimpleJson(1, "单号不匹配，请确保邀请码与单号对应或检查单号是否正确");
        }
    }

    @Override
    public void detectExpiredJoinApplicationRecords() {
        joinMapper.detectExpiredJoinApplicationRecords();
    }

    @Override
    public boolean getSapIfOpenJoinFunction() {
        return cacheService.getSapIfOpenJoinFunction();
    }

    @Override
    public SimpleJson updateSapIfOpenJoinFunction() {
        if (getUserByUserName(JwtUtil.getUserForToken()).getRole() != 1) {
            //只有会长能执行
            return new SimpleJson(2, "权限不足");
        }
        try {
            cacheService.updateSapIfOpenJoinFunction();
        } catch (Exception e) {
            return SimpleJson.FAILURE;
        }
        return SimpleJson.SUCCESS;
    }

    @Override
    public List<JoinManagerVo> getJoinManagerVos() {
        List<JoinManagerVo> joinManagerVos = joinMapper.getJoinManagerVos();
        //填充真实姓名
        Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
        for (JoinManagerVo joinManagerVo : joinManagerVos) {
            joinManagerVo.setName(cacheService.getRealNameCache(realNameCacheMap, joinManagerVo.getUsername()));
        }
        return joinManagerVos;
    }

    /**
     * 填充管理员表
     * <p>
     * 清除原表中的数据，将当前(副)部长及以上职位用户加入管理表作为备用管理员，默认情况下刚更新管理表时只有会长直接是管理员
     * (事务支持)
     * <p>
     * 此方法和BmsService中一模一样，用于避免循环引用
     */
    @Transactional(rollbackFor = Exception.class)
    void fillBmsManagerTable() {
        //清空当前管理表
        bmsMapper.clearBmsManagerTable();
        //将所有部长及以上职务的成员的学号插入管理表 (默认情况不是管理员，只是默认管理员)
        List<String> allMinistersUsername = userMapper.getAllMinistersUsername();
        for (String username : allMinistersUsername) {
            bmsMapper.addBmsManager(username);
        }
        //单独获取会长学号，将会长设为管理员
        String presidentUserName = userMapper.getPresidentUserName();
        bmsMapper.updateBmsManager(presidentUserName, true);
    }

    @Override
    public SapJoinApplication getJoinApplicationByCode(String invitationCode) {
        return joinMapper.getSapJoinApplicationByCode(invitationCode);
    }

    @Override
    public SapJoinManager getSapJoinManager(String username) {
        return joinMapper.getSapJoinManager(username);
    }

    @Override
    public List<SapJoinApplication> getAbnormalJoinApplication() {
        return joinMapper.getAbnormalJoinApplication();
    }

    @Override
    public SimpleJson clearJoinApplicationPaymentTransferNumber(String username) {
        if (username == null) {
            return new SimpleJson(2, "参数为空");
        }
        SapJoinApplication joinApplication = joinMapper.getSapJoinApplication(username);
        if (joinApplication == null) {
            return new SimpleJson(3, "未查找到对应记录");
        }
        //没填写单号不管
        if (joinApplication.getJoinApplicationPaymentTransferNumber() == null) {
            return new SimpleJson(4, "该记录没填写单号");
        }
        //已经通过审核(成为正式会员)不管
        if (joinApplication.getJoinApplicationResult() == 1) {
            return new SimpleJson(5, "通过审核的记录不能清除转账单号");
        }
        joinMapper.clearJoinApplicationPaymentTransferNumber(username);
        return new SimpleJson(0, "清空单号成功");
    }

    @Override
    public String getRealName(String username) {
        return userMapper.getRealNameByUserName(username);
    }

    /**
     * @param sapOnlinePeople 在线人员信息
     */
    @Override
    public void addOnlinePeople(SapOnlinePeople sapOnlinePeople) {
        List<SapOnlinePeople> onlinePeopleMessage = userMapper.getOnlinePeopleMessage();
        for (int i = onlinePeopleMessage.size() - 1; i >= 0; i--) {
            if (Objects.equals(onlinePeopleMessage.get(i).getOnlinePeopleTime(), sapOnlinePeople.getOnlinePeopleTime()) && Objects.equals(onlinePeopleMessage.get(i).getOnlinePeopleUsername(), sapOnlinePeople.getOnlinePeopleUsername()) && Objects.equals(onlinePeopleMessage.get(i).getOnlinePeopleFullTime(), sapOnlinePeople.getOnlinePeopleFullTime())) {
                return;
            }
        }
        userMapper.addOnlinePeople(sapOnlinePeople);
    }


    @Override
    public SimpleJson getOnlinePeopleMessageCopy() {
        List<SapOnlinePeople> onlinePeopleMessage = userMapper.getOnlinePeopleMessage();
        List<String> fullList = new ArrayList<>();
        for (SapOnlinePeople sapOnlinePeople : onlinePeopleMessage) {
            if (!fullList.contains(sapOnlinePeople.getOnlinePeopleFullTime())) {
                fullList.add(sapOnlinePeople.getOnlinePeopleFullTime());
            }
        }
        List<List<String>> timeListSum = new ArrayList<>();
        for (String fullTime : fullList) {
            List<String> timeList = new ArrayList<>();
            boolean check = false;
            for (SapOnlinePeople onlinePeople : onlinePeopleMessage) {
                if (Objects.equals(onlinePeople.getOnlinePeopleFullTime(), fullTime)) {
                    check = true;
                    if (!timeList.contains(onlinePeople.getOnlinePeopleTime())) {
                        timeList.add(onlinePeople.getOnlinePeopleTime());
                    }
                } else {
                    if (check) {
                        break;
                    }
                }
            }
            timeListSum.add(timeList);
        }

        int index = 0;
        List<OnlineFullVo> onlineFullVos = new ArrayList<>();
        int onlineFullId = 1;
        for (List<String> fullLists : timeListSum) {
            OnlineFullVo onlineFullVo = new OnlineFullVo();
            List<OnlineTime> fullTime = new ArrayList<>();
            for (String time : fullLists) {
                OnlineTime onlineTime = new OnlineTime();
                List<UserAndName> list = new ArrayList<>();
                boolean check = false;
                for (SapOnlinePeople sapOnlinePeople : onlinePeopleMessage) {
                    String s = fullList.get(index);
                    if (Objects.equals(sapOnlinePeople.getOnlinePeopleTime(), time) && Objects.equals(sapOnlinePeople.getOnlinePeopleFullTime(), s)) {
                        list.add(new UserAndName(onlineFullId++, sapOnlinePeople.getOnlinePeopleUsername(), sapOnlinePeople.getOnlinePeopleName()));
                        check = true;
                    } else {
                        if (check) {
                            break;
                        }
                    }
                }
                onlineTime.setId(onlineFullId++);
                onlineTime.setTitle(time);
                onlineTime.setData(list);
                fullTime.add(onlineTime);
            }
            onlineFullVo.setId(onlineFullId++);
            onlineFullVo.setTitle(fullList.get(index++));
            onlineFullVo.setData(fullTime);
            onlineFullVos.add(onlineFullVo);
        }
        return new SimpleJson(onlineFullVos);
    }

    @Override
    public void addAdviceOrQuestion(SapAdviceOrQuestion sapAdviceOrQuestion) {
        userMapper.addAdviceOrQuestion(sapAdviceOrQuestion);
        sapAdviceOrQuestion.setUserRealName(userMapper.getRealNameByUserName(sapAdviceOrQuestion.getUsername()));
    }

    @Override
    public SimpleJson sendAdviceOrQuestionOfNotice(SapAdviceOrQuestion sapAdviceOrQuestion) {
        String content = EmailUntil.emailForCommitAdviceOrQuestion(sapAdviceOrQuestion);
        User president = getPresidentUserInfo();
        iMailService.sendHtmlMail(president.getQq() + "@qq.com", "新的建议或BUG反馈", content);
        return new SimpleJson(0, "感谢反馈");
    }

    @Override
    public List<Integer> getSessionYear() {
        List<Integer> sessionYear = userMapper.getSessionYear();
        Collections.sort(sessionYear);
        return sessionYear;
    }

    @Override
    public Map<String, List<SapJoinApplication>> getSubmittedJoinApplicationByManager() {
        List<SapJoinApplication> applications = joinMapper.getSubmittedJoinApplicationByManager(JwtUtil.getUserForToken());
        if (applications == null || applications.isEmpty()) {
            return null;
        }
        //根据是否已被审核分类
        Map<String, List<SapJoinApplication>> map = new HashMap<>(2);
        List<SapJoinApplication> unapprovedRecords = new ArrayList<>();
        List<SapJoinApplication> auditedApplications = new ArrayList<>();
        for (SapJoinApplication application : applications) {
            if (application.getJoinApplicationResult() == 0) {
                unapprovedRecords.add(application);
            } else {
                auditedApplications.add(application);
            }
        }
        map.put("未审核", unapprovedRecords);
        map.put("已审核", auditedApplications);
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SimpleJson directUpgrade(String username, String accounting) throws Exception {
        //获取使用接口的管理员的学号
        String managerUsername = JwtUtil.getUserForToken();
        //判断输入的转账标识是否有效
        if (!"no".equals(accounting) && !"yes".equals(accounting)) {
            return new SimpleJson(1, "账单标识输入有误");
        }
        //根据输入的学号找用户信息
        User user = userMapper.getUserByUserName(username);
        if(user==null) {
            return new SimpleJson(1,"用户不存在");
        }
        if (user.getRole() != 12) {
            return new SimpleJson(1, "该学号对应用户已经是正式会员");
        }
        //查找是否有相应的申请表记录
        SapJoinApplication application = joinMapper.getSapJoinApplication(username);
        Map<String, String> realNameCacheMap = cacheService.getRealNameCacheMap();
        String applicantName = cacheService.getRealNameCache(realNameCacheMap, username);
        String managerName = cacheService.getRealNameCache(realNameCacheMap, managerUsername);
        //没有申请表记录，就添加一个
        if (application == null) {
            application = new SapJoinApplication();
            //设置学号对应用户的信息
            application.setJoinApplicantUsername(username);
            application.setJoinApplicantName(applicantName);
            application.setJoinApplicantQq(user.getQq());
            //设置操作人为匹配的负责人
            application.setJoinManagerUsername(managerUsername);
            application.setJoinManagerName(managerName);
            application.setJoinManagerQq(userMapper.getUserByUserName(managerUsername).getQq());
            //生成邀请码(6位随机大写字母)
            application.setJoinApplicationInvitationCode(StringCodeUtil.createUppercaseStringCode(6));
            //加入数据库
            joinMapper.addSapJoinApplication(application);
            //重新查询获取记录 (因为没id,只能再查询一下)
            application = joinMapper.getSapJoinApplication(username);
        } else {
            //原负责人学号
            String oldManagerUsername = application.getJoinManagerUsername();
            //重新分配操作人为匹配的负责人
            application.setJoinManagerUsername(managerUsername);
            application.setJoinManagerName(managerName);
            application.setJoinManagerQq(userMapper.getUserByUserName(managerUsername).getQq());
            joinMapper.createSapJoinApplicationAgain(application);
        }
        //填写单号为"由xxx手动升级为会员"
        joinMapper.setJoinApplicationPaymentTransferNumber(application.getJoinApplicationId(), "由" + managerName + "手动升级为会员");
        //升级会员
        userMapper.updateRole(11, username);
        //修改申请表结果字段
        joinMapper.updateJoinApplicationResult(username, 1);
        //对User_history的信息进行修改，从例如:游客-->2021级正式成员
        userMapper.updateHistory(username, dynamicService.getYear() + "级正式成员");
        //对user_posts的信息进行添加，这个表存在每一届的所有正式成员以及部长及其会长
        userMapper.addPosts(username, userMapper.getPostByRole(11), dynamicService.getYearForInt(), 11);
        //修改权限从游客到正式成员
        userMapper.updateUserRole(username, ConstantUntil.USER_ROLE_PERMISSIONS_FOUR);
        //对接财务表
        //addBill有主动抛出异常
        if("yes".equals(accounting)) {
            billService.addBill(1, "会费缴纳", new BigDecimal(30), new Timestamp(System.currentTimeMillis()), "会费缴纳账单,执行审批接口的管理员学号为" + managerUsername, null, username, applicantName);
        }
        //邮件/站内通知
        String email = EmailUntil.emailForUserJoinSuccess(applicantName);
        String notice = "[入会成功] 恭喜你成为软件协会的一员，期望你能在协会中有所收获，祝你成功！";
        sendNotice(new NoticeDto(username, notice, null));
        try {
            iMailService.sendHtmlMail(application.getJoinApplicantQq() + "@qq.com", "入会成功", email);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //更新Redis里的权限内容(从数据库中获取添加)
        //从redis中获取用户信息
        Map<String, Object> cacheMap = redisCache.getCacheMap(ConstantUntil.SAP_LOGIN);
        String userJson = (String) cacheMap.get(username);
        LoginUser loginUser = JSON.parseObject(userJson, LoginUser.class);
        loginUser.setPermissions(menuMapper.selectPermsByUserId(username));
        //把完整的用户信息存入redis username作为key
        String userJsonRedis = com.alibaba.fastjson2.JSON.toJSONString(loginUser);
        cacheService.loginCacheUserToRedis(username, userJsonRedis);
        return SimpleJson.SUCCESS;
    }
}
